/* *
 * --ライセンスについて--
 *
 * 「本ファイルの内容は Mozilla Public License Version 1.1 (「本ライセンス」)
 * の適用を受けます。
 * 本ライセンスに従わない限り本ファイルを使用することはできません。
 * 本ライセンスのコピーは http://www.mozilla.org/MPL/ から入手できます。
 *
 * 本ライセンスに基づき配布されるソフトウェアは、「現状のまま」で配布されるものであり、
 * 明示的か黙示的かを問わず、いかなる種類の保証も行われません。
 * 本ライセンス上の権利および制限を定める具体的な文言は、本ライセンスを参照してください。
 *
 * オリジナルコードおよび初期開発者は、N_H (h.10x64@gmail.com) です。
 *
 * N_H によって作成された部分の著作権表示は次のとおりです。
 *
 * Copyright (C)N_H 2012
 *
 * このファイルの内容は、上記に代えて、
 * GNU General License version2 以降 (以下 GPL とする)、
 * GNU Lesser General Public License Version 2.1 以降 (以下 LGPL とする)、
 * の条件に従って使用することも可能です。
 * この場合、このファイルの使用には上記の条項ではなく GPL または LGPL の条項が適用されます。
 * このファイルの他者による使用を GPL または LGPL の条件によってのみ許可し、
 * MPL による使用を許可したくない対象者は、上記の条項を削除することでその意思を示し、
 * 上記条項を GPL または LGPL で義務付けられている告知およびその他の条項に置き換えてください。
 * 対象者が上記の条項を削除しない場合、
 * 受領者は MPL または GPL または LGPL ライセンスのいずれによってもこのファイルを
 * 使用することができます。」
 *
 * -- License --
 *
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License。You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND、either express or implied。See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Initial Developer of the Original Code is
 *   N_H (h.10x64@gmail.com).
 *
 * Portions created by the Initial Developer are Copyright (C)N_H 2012
 * the Initial Developer。All Rights Reserved.
 *
 * Alternatively、the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL")、or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above。If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL、and not to allow others to
 * use your version of this file under the terms of the MPL、indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL。If you do not delete
 * the provisions above、a recipient may use your version of this file under
 * the terms of any one of the MPL、the GPL or the LGPL.
 *
 * */
package com.magiciansforest.audio.soundrenderer.gui;

import com.jme3.app.Application;
import com.jme3.app.state.AbstractAppState;
import com.jme3.app.state.AppStateManager;
import com.magiciansforest.audio.soundrenderer.Viewer;
import com.magiciansforest.audio.soundrenderer.logic.Movie;
import com.magiciansforest.audio.soundrenderer.logic.MovieFile;
import com.magiciansforest.audio.soundrenderer.logic.mmd.VMD;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.NiftyEventSubscriber;
import de.lessvoid.nifty.controls.DropDownSelectionChangedEvent;
import de.lessvoid.nifty.controls.ListBoxSelectionChangedEvent;
import de.lessvoid.nifty.controls.RadioButtonStateChangedEvent;
import de.lessvoid.nifty.controls.TextFieldChangedEvent;
import de.lessvoid.nifty.elements.events.NiftyMousePrimaryClickedEvent;
import de.lessvoid.nifty.elements.events.NiftyMousePrimaryClickedMovedEvent;
import de.lessvoid.nifty.screen.Screen;
import de.lessvoid.nifty.screen.ScreenController;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;

/**
 *
 * @author N_H
 */
public class MovieDataInterface extends AbstractAppState implements ScreenController {
    private static final String FILE_PANEL = "filePanel";
    private static final String PMD_PANEL = "pmdPanel";
    private static final String SOUND_PANEL = "soundPanel";
    private static final String AIR_PANEL = "airPanel";
    private static final String CAMERA_PANEL = "cameraPanel";
    private Movie mov;
    private Nifty nifty;
    private Screen screen;
    private HashMap<String, NiftyPanel> panels = new HashMap<String, NiftyPanel>();
    private List<VMD> loadedVMDFiles = new ArrayList<VMD>();
    
    /* Override methods */
    @Override
    public void bind(Nifty nifty, Screen screen) {
        this.nifty = nifty;
        this.screen = screen;
        
        /* Initialize panels */
        //File panel
        NiftyFilePanel filePanel = new NiftyFilePanel();
        filePanel.bind(mov, screen.findElementByName(FILE_PANEL));
        panels.put(FILE_PANEL, filePanel);
        //PMD panel
        NiftyPMDPanel pmdPanel = new NiftyPMDPanel();
        pmdPanel.bind(mov, screen.findElementByName(PMD_PANEL));
        panels.put(PMD_PANEL, pmdPanel);
        //Sound panel
        NiftySoundPanel soundPanel = new NiftySoundPanel();
        soundPanel.bind(mov, screen.findElementByName(SOUND_PANEL));
        panels.put(SOUND_PANEL, soundPanel);
        //Camera panel
        NiftyCameraPanel cameraPanel = new NiftyCameraPanel();
        cameraPanel.bind(mov, screen.findElementByName(CAMERA_PANEL));
        panels.put(CAMERA_PANEL, cameraPanel);
        //Air panel
        NiftyAirPanel airPanel = new NiftyAirPanel();
        airPanel.bind(mov, screen.findElementByName(AIR_PANEL));
        panels.put(AIR_PANEL, airPanel);
        
        MoviePositionSliderControl slider = screen.findControl("moviePositionSlider", MoviePositionSliderControl.class);
        slider.setMovie(mov);
        
        Iterator<Map.Entry<String, NiftyPanel>> itr = panels.entrySet().iterator();
        while (itr.hasNext()) {
            Map.Entry<String, NiftyPanel> entry = itr.next();
            entry.getValue().hide();
        }
    }

    @Override
    public void onEndScreen() {
    }

    @Override
    public void onStartScreen() {
    }

    @Override
    public void initialize(AppStateManager stateManager, Application app) {
        super.initialize(stateManager, app);
    }

    @Override
    public void update(float tpf) {
    }
    
    /* NiftyEvent */
    //PMDPanel
    @NiftyEventSubscriber (id="pmdPanelListBox")
    public void onPmdPanelListBoxSelectionChanged(final String id, final ListBoxSelectionChangedEvent<String> evt) {
        ((NiftyPMDPanel) panels.get(PMD_PANEL)).onListBoxSelectionChange(id, evt);
    }
    
    //Slider
    @NiftyEventSubscriber (id="moviePositionSlider")
    public void onSoundPositionSliderMouseDragged(final String id, final NiftyMousePrimaryClickedMovedEvent evt) {
        screen.findControl("moviePositionSlider", MoviePositionSliderControl.class).mouseDragged(evt);
    }
    
    @NiftyEventSubscriber (id="moviePositionSlider")
    public void onSoundPositionSliderMouseClicked(final String id, final NiftyMousePrimaryClickedEvent evt) {
        screen.findControl("moviePositionSlider", MoviePositionSliderControl.class).mouseClicked(evt);
    }
    
    //SoundPanel
    @NiftyEventSubscriber (pattern="sound.*TextField")
    public void onSoundNameTextChange(final String id, final TextFieldChangedEvent evt) {
        ((NiftySoundPanel) panels.get(SOUND_PANEL)).onTextFieldChage(evt);
    }
    
    @NiftyEventSubscriber (id="soundListBox")
    public void onSoundListSelectionChange(final String id, final ListBoxSelectionChangedEvent<String> evt) {
        ((NiftySoundPanel) panels.get(SOUND_PANEL)).onSoundListSelectionChange(evt);
    }
    
    @NiftyEventSubscriber (id="parentDropDown")
    public void onParentDropDownSelectionChange(final String id, final DropDownSelectionChangedEvent<String> evt) {
        ((NiftySoundPanel) panels.get(SOUND_PANEL)).onParentDropDownSelectionChange(evt);
    }
    
    @NiftyEventSubscriber (id="boneDropDown")
    public void onBoneDropDownSelectionChange(final String id, final DropDownSelectionChangedEvent<String> evt) {
        ((NiftySoundPanel) panels.get(SOUND_PANEL)).onBoneDropDownSelectionChange(evt);
    }
    
    //Camera Panel
    @NiftyEventSubscriber (id="useControllerRadio") 
    public void onUseControllerRadioSelected(final String id, final RadioButtonStateChangedEvent event) {
        mov.useController(true);
    }
    
    @NiftyEventSubscriber (id="useVMDRadio") 
    public void onUseVMDRadioSelected(final String id, final RadioButtonStateChangedEvent event) {
        mov.useController(false);
    }
    
    @NiftyEventSubscriber (id="cameraSpeedTextField")
    public void onCameraSpeedTextFieldChanged(final String id, final TextFieldChangedEvent evt) {
        ((NiftyCameraPanel) panels.get(CAMERA_PANEL)).cameraSpeedTextFieldChanged(evt.getText());
    }
    
    //Air Panel
    @NiftyEventSubscriber (id="tempTextField")
    public void onTempTextFieldChanged(final String id, final TextFieldChangedEvent evt) {
        ((NiftyAirPanel) panels.get(AIR_PANEL)).onTempTextFieldChanged(evt.getText());
    }
    
    @NiftyEventSubscriber (id="atmTextField")
    public void onAtmTextFieldChanged(final String id, final TextFieldChangedEvent evt) {
        ((NiftyAirPanel) panels.get(AIR_PANEL)).onAtmTextFieldChanged(evt.getText());
    }
    
    @NiftyEventSubscriber (id="humidityTextField")
    public void onHumidityTextFieldChanged(final String id, final TextFieldChangedEvent evt) {
        ((NiftyAirPanel) panels.get(AIR_PANEL)).onHumidityTextFieldChanged(evt.getText());
    }
    
    /* Nifty calls these methods */
    public void reset() {
        int res = JOptionPane.showConfirmDialog(null, "Save this settings?", "Reset", JOptionPane.YES_NO_CANCEL_OPTION);
        if (res == JOptionPane.YES_OPTION) {
            saveProjectFile();
            mov.reset();
        } else if (res == JOptionPane.NO_OPTION) {
            mov.reset();
        }
    }
    
    public void loadProjectFile() {
        mov.setMovieStatus(Movie.PAUSED);
        
        JFileChooser chooser = new JFileChooser("./");
        chooser.setFileFilter(new FileNameExtensionFilter("Project File", "js"));
        if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            File f = chooser.getSelectedFile();
            try {
                MovieFile.readMovieFile(f, mov);
            } catch (Exception e) {
                Logger.getLogger(Viewer.LOGGER_NAME).log(Level.SEVERE, e.getMessage());
            }
        }
    }
    
    public void saveProjectFile() {
        mov.setMovieStatus(Movie.PAUSED);
        
        JFileChooser chooser = new JFileChooser("./");
        chooser.setFileFilter(new FileNameExtensionFilter("Project File", "js"));
        if (chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
            String path = chooser.getSelectedFile().getAbsolutePath();
            if (!path.substring(path.lastIndexOf('.')).equals(".js")) {
                path += ".js";
            }
            
            File f = new File(path);
            try {
                MovieFile.writeMovieFile(f, mov);
            } catch (Exception e) {
                Logger.getLogger(Viewer.LOGGER_NAME).log(Level.SEVERE, e.getMessage());
            }
        }
    }
    
    public void loadWavFile() {
        JFileChooser chooser = new JFileChooser("./");
        chooser.setFileFilter(new FileNameExtensionFilter("Wav File", "wav"));
        if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            String path = chooser.getSelectedFile().getAbsolutePath();
            long selectedID = ((NiftySoundPanel) panels.get(SOUND_PANEL)).getSelectedID();
            try {
                mov.setWavFile(selectedID, path);
            } catch (IOException ioe) {
                Logger.getLogger(Viewer.LOGGER_NAME).log(Level.SEVERE, ioe.getMessage());
                JOptionPane.showMessageDialog(null, ioe.getMessage());
            }
        }
    }
    
    public void addSoundSource() {
        mov.addSoundSource();
    }
    
    public void removeSoundSource() {
        mov.removeSoundSource(((NiftySoundPanel) panels.get(SOUND_PANEL)).getSelectedID());
    }

    public void loadPMDFile() {
        JFileChooser chooser = new JFileChooser("./");
        chooser.setFileFilter(new FileNameExtensionFilter("PMDファイル", "pmd"));
        if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            String path = chooser.getSelectedFile().getAbsolutePath();
            mov.loadPMDFile(path);
        }
    }
    
    public void loadVMDFile() {
        ((NiftyPMDPanel) panels.get(PMD_PANEL)).loadVMDFile();
    }
    
    public void loadCameraVMD() {
        JFileChooser chooser = new JFileChooser("./");
        chooser.setFileFilter(new FileNameExtensionFilter("Camera VMD File", "vmd"));
        if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
            try {
                VMD cameraVMD = new VMD(chooser.getSelectedFile());
                mov.bindCameraVMD(cameraVMD);
            } catch (IOException ioe) {
                Logger.getLogger(Viewer.LOGGER_NAME).log(Level.SEVERE, ioe.getMessage());
            }
        }
    }
    
    public void exit() {
        System.exit(0);
    }
    
    /* Misc. */ 
    public void setMovie(Movie mov) {
        this.mov = mov;
    }
    
    public void removePMD() {
        ((NiftyPMDPanel) panels.get(PMD_PANEL)).removePMD();
    }
    
    public void switchMainPanel(String panelName) {
        if (!panels.containsKey(panelName)) {
            return;
        }
        
        NiftyPanel showPanel = null;
        Iterator<String> keys = panels.keySet().iterator();
        while (keys.hasNext()) {
            String key =  keys.next();
            if (key.equals(panelName)) {
                showPanel = panels.get(key);
            } else {
                panels.get(key).hide();
            }
        }
        
        if (showPanel.isVisible()) {
            showPanel.hide();
        } else {
            showPanel.show();
        }
    }
}
